Skip to content

feat(sdk,cli,mcp): agent-DX blob CDN diagnostics (v1.45)#117

Merged
MajorTal merged 1 commit into
mainfrom
agent-dx-blob-cdn
Apr 27, 2026
Merged

feat(sdk,cli,mcp): agent-DX blob CDN diagnostics (v1.45)#117
MajorTal merged 1 commit into
mainfrom
agent-dx-blob-cdn

Conversation

@MajorTal
Copy link
Copy Markdown
Collaborator

Summary

Coordinated public-repo half of the v1.33 agent-DX blob CDN release. All additive — no existing API surface broken.

Pairs with the private-repo PR that ships the gateway + infra + schema changes. Merge that one first so the canonical site/llms.txt carries the /storage/v1/blobs/diagnose endpoint row; the sync.test.ts llms.txt alignment assertion in this PR then auto-passes when re-run locally.

After both PRs land, run npm publish from this branch in the coordinated release window with the v1.33 backend cutover. Version is already bumped to 1.45.0 (commit 143f408).

What's in this PR

SDK (sdk/src/namespaces/blobs.ts, blobs.types.ts)

  • Widen client.blobs.put return into AssetRef: keeps the snake_case fields (size_bytes, sha256, immutable_url) for back-compat AND adds size, contentSha256, contentType, immutableUrl, etag, sri, contentDigest, cacheKind, cdn: { version, invalidationId, invalidationStatus, ready, hint }.
  • buildAssetRef derives etag/sri/contentDigest locally from the SHA so the SDK surface is stable across gateway versions (older gateways without the cdn envelope still work — buildAssetRef fills safe defaults).
  • New helpers:
    • client.blobs.diagnoseUrl(projectId, url) → diagnose envelope
    • client.blobs.waitFresh(projectId, { url, sha256, timeoutMs? }) → polls with exponential backoff, returns { fresh, observedSha256, attempts, elapsedMs, vantage } — never throws on timeout.

Signature note: the original spec showed waitFresh({ key, sha256, timeoutMs }) without a projectId. I added projectId as the first arg and accept url instead of key, matching the existing namespace convention (put(projectId, key, ...), get(projectId, key)). The url is what callers already get from blobs.put, so no extra plumbing needed.

CLI

  • cli/lib/blob.mjs: new run402 blob diagnose <url> subcommand. Exit code 0 if observedSha256 === expectedSha256, 1 otherwise — agents can until run402 blob diagnose <url>; do sleep 1; done. Vantage caveat printed to stderr so it doesn't pollute pipes.
  • cli/lib/cdn.mjs: new run402 cdn wait-fresh <url> --sha <hex> [--timeout <secs>] namespace + subcommand. Exit 0 when fresh, 1 on timeout.
  • Both surfaces have --help documenting input/output/exit-code semantics + the "mutable URLs only" caveat.
  • openclaw/scripts/cdn.mjs re-exports cdn.mjs to keep CLI ↔ OpenClaw parity.

MCP tools (src/tools/blob-diagnose.ts, blob-wait-fresh.ts)

  • diagnose_public_url — returns the diagnose envelope, formatted with summary + JSON.
  • wait_for_cdn_freshness — polls; returns isError=true on timeout so an agent can branch into the immutableUrl fallback. Tool descriptions explicitly tag mutability ("mutable URLs only").

Docs

  • SKILL.md: blob_put section now describes the AssetRef return shape; new ## Prefer immutableUrl in generated HTML/CSS/JS guidance with reasoning (read-after-write correctness, integrity via SRI). New tool sections for diagnose_public_url + wait_for_cdn_freshness.
  • cli/llms-cli.txt: blob section rewritten with the agent-DX guidance + AssetRef field table.

Out of scope (deferred to followups)

  • Browser-side SDK helpers (auth surface concerns)
  • client.blobs.stats(...), run402 cdn tail, get_cdn_metrics, explain_blob_cache_state — need CloudFront log ingestion
  • AssetRef on every per-file /deploy/v1/commit response (only on blobs.put for v1)

Test plan

  • npx tsc --noEmit clean
  • SDK blobs unit tests: 22/22 pass (8 new)
  • All SDK unit tests: 133/133 pass
  • SKILL.test.ts: 21/21 pass
  • sync.test.ts: 17/20 pass, 1 fail, 2 skipped — the single failure is the cross-repo llms.txt alignment assertion (reads ~/Developer/run402-private/site/llms.txt from main). Auto-passes after the paired private PR merges. CI in this repo skips the suite when the path is absent.
  • CLI smoke test: node cli/cli.mjs cdn --help and node cli/cli.mjs blob diagnose --help print structured help
  • npm run build passes (verified locally; CI re-checks)
  • npm publish after the private cutover lands (operator step in coordinated release window)

🤖 Generated with Claude Code

Coordinated public-repo half of the v1.33 agent-DX blob CDN release. All additive — no existing API surface broken.

SDK (sdk/src/namespaces/blobs.{ts,types.ts}):

- Widen blobs.put return into AssetRef: keeps the snake_case fields for back-compat AND adds size, contentSha256, contentType, immutableUrl, etag, sri, contentDigest, cacheKind, cdn:{version,invalidationId,invalidationStatus,ready,hint}.

- buildAssetRef derives etag/sri/contentDigest locally from the SHA so the SDK surface is stable across gateway versions.

- New helpers: client.blobs.diagnoseUrl(projectId, url) and client.blobs.waitFresh(projectId, {url, sha256, timeoutMs?}). Signed slightly differently from the spec scenarios (added projectId first arg) for consistency with put/get/ls.

- 8 new tests in blobs.test.ts (22 total).

CLI (cli/lib/blob.mjs, cli/lib/cdn.mjs, cli/cli.mjs, openclaw/scripts/cdn.mjs):

- run402 blob diagnose <url> — exit 0 on SHA match, 1 otherwise (shell-loop friendly).

- run402 cdn wait-fresh <url> --sha <hex> [--timeout <secs>] — polls until fresh.

- Both --help docs include exit-code semantics and the vantage caveat.

MCP tools (src/tools/blob-{diagnose,wait-fresh}.ts, src/index.ts):

- diagnose_public_url + wait_for_cdn_freshness with explicit agent guidance ('mutable URLs only').

- wait_for_cdn_freshness returns isError=true on timeout so agents branch into the immutableUrl fallback.

Docs (SKILL.md, cli/llms-cli.txt):

- 'Prefer immutableUrl in generated HTML/CSS/JS' guidance with reasoning (read-after-write correctness, integrity via SRI).

- New tool sections for diagnose_public_url + wait_for_cdn_freshness.

Notes:

- sync.test.ts updated for the new SURFACE rows + cdn namespace; the llms.txt-alignment assertion fails locally until the private-repo PR merges (it reads ~/Developer/run402-private/site/llms.txt). CI in the public repo skips the suite when the path is absent.

- Version is already 1.45.0 (chore: bump in 143f408). After this PR merges, run npm publish in coordination with the v1.33 backend cutover.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@MajorTal MajorTal merged commit e812399 into main Apr 27, 2026
4 checks passed
@MajorTal MajorTal deleted the agent-dx-blob-cdn branch April 27, 2026 18:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant